/*
 * Scheduler.h
 *
 *  Created on: Dec 12, 2011
 *      Author: quotrader
 */

#ifndef SCHEDULER_H_
#define SCHEDULER_H_

#include "../Algorithm/Algorithm.h"
#include <sys/trace.h>
#include <sys/neutrino.h>

class Scheduler {
public:
	Algorithm *algr;
	int maxPriority;
	int minPriority;
	int scheduleId;
	int startPriority;
	int priorityIncr;
	Scale *scale;
	TaskMng *tMng;
	pthread_t ctrThread;
	sem_t semId;

	Scheduler();
	void setup(Scale *scale,TaskMng *tMng);
	virtual void execute ();
	int setupPuls();
	static void *control(void *object) {

			// check the received object is a correct one
			Scheduler *ci = ((Scheduler *) object);
			if (!ci) return NULL;

			// definitions an initializations
			sem_wait(&ci->semId);
			int chid 				= ci->setupPuls();
			bool exitFlag			=true;
			struct _pulse pulse;
			unitTime now;
			Task *tasks = ci->tMng->tasks;
			int numTask = ci->tMng->numTask;
			sched_param param;
			char tmp[100];
			Task *currTask;

			// catching-pulses loop
			do{
				// set it to highest priority
				pthread_setschedprio(ci->ctrThread,ci->startPriority+(ci->priorityIncr*ci->tMng->numTask)+ci->priorityIncr);

				// receive pulses
				MsgReceive(chid, &pulse, sizeof(pulse), NULL);

				// set it to highest priority
				pthread_setschedprio(ci->ctrThread,ci->startPriority+(ci->priorityIncr*ci->tMng->numTask)+ci->priorityIncr);

				pthread_getschedparam(ci->ctrThread,NULL,&param);
				pthread_getname_np(pthread_self(),tmp,sizeof(tmp));
				//cout<<"got pulse:"<<ci->scale->getUniTime().unit<<" my Prio:"<<param.sched_curpriority<<"&"<<param.sched_priority<<" Name:"<<tmp<<"\n";
				exitFlag=true;

				// check all periods and release tasks if they not released
				for(int i=0; i<numTask; i++){
					now= ci->scale->getUniTime();
					if((tasks[i].exeCycls*tasks[i].period)<=now.unit)
						if(tasks[i].status == "BLOCKED"){
							//cout<<"task#"<<tasks[i].id<<" is blucked, "<<ci->scale->getUniTime().unit<<"\n";
							sem_post(&tasks[i].semId);
							tasks[i].status= "RELEASED";
						}
				}

				// check if all tasks get executed at least one time
				for(int i=0; i<numTask; i++){
					if(!tasks[i].done)exitFlag=false;
					if(tasks[i].running)currTask=&tasks[i];
				}

				if(exitFlag)ci->scale->finishAll=true;
				//sem_post(&currTask->semId);

			}while(!exitFlag);

			return NULL;
		}

};

#endif /* SCHEDULER_H_ */
